﻿package com.unifiedfield {
	import flash.display.*;
	import flash.events.*;
	import flash.utils.Timer;
	import com.unifiedfield.*;
	// import caurina.transitions.Tweener;

	public class WatermarkMaker extends MovieClip {
		private var threshold:Number = 3000; //the threshold to beat

		
		public var strArray = new Array;
		public var envelope = new Array;
		
		public var multscale = 0.015;
		public var fallaway = 1.2; //factor that the wave reduces by for each move to right
		public var maxmove = 15; //most it can change by in one move
		public var DCOffset = 0;
		public var limitPoints = 2400;
		public var circleX:Number = 0;
		public var circleY:Number = 0;
		
		private var counter = 0;
		public var cEnvOut:Array = new Array();
		public var cEnvIn:Array = new Array();
		private var numPoints:Number = 0;  // num of points that we have
		public var numData:Number = 0; //amount of data we've gotten so far (just for testing)
		
		private var holdWave:Sprite = new Sprite();
		private var shpCircle:Shape = new Shape;
		public var clrOutline = 0xCC3300;
		public var clrWave = 0x99FF00;
		
		private var ringsize = 140; //how wide the ring is
		private var watermarkScale = 2;  // factor by which to scale down the watermark
		
		private var animCount = 0;  // counter for animation of waveform curling
		private var lineColor = 0;
		private var fillColor = 0;
				// in example, inits to 53 and 450, respectively
		public function WatermarkMaker(cx:Number = 0, cy:Number = 0, ringRadius:Number = 0,l=0,c=0) {
			circleX = cx;
			circleY = cy;
			ringsize = ringRadius;
			numPoints = 0;  //first, 1 point and then end (first and end will be zero)
			envelope.push([0,0]);
			strArray.push("0"); //set a zero at the start
			lineColor=l;
			fillColor=c;
		}
		public function setcolor(l,f){
			lineColor=l;
			fillColor=f;
		}
		public function waveReset(spr:Sprite) {
			spr.alpha = 1;
			numPoints = 0;
			numData = 0;
			strArray = [];
			drawSoundWave(circleX, circleY, spr);
		}
		
		public function beginDrawing(shp:Shape, spr:Sprite):void {
			shpCircle = shp;
			var wavAnimationTimer:Timer = new Timer(30,50);  // timer for animating waveform as it curls
			wavAnimationTimer.addEventListener(TimerEvent.TIMER, doCurl);
			wavAnimationTimer.start();
			spr.graphics.clear();
		}
		
		public function addSamplePoints (sIn, spr:Sprite) {
			var newArray = new Array();
			newArray = sIn.split(/,/);
			for (var i=0; i<newArray.length-1; i++) {  //length-1 to chop off the last one, cuz the return ends with
			// a comma, meaning the last entry in the newArray array is not valid
				strArray.push(newArray[i]);
			}
			numData = strArray.length;
			var strTest = new String();
			for (i=strArray.length-1; i>=0; i--) {
				strTest = strTest+"_"+strArray[i];
			}
			expandWave(spr);
		}
		private function expandWave(spr:Sprite) {
			
			while (numData>numPoints && numPoints<limitPoints) {
				var i=numPoints;
				if (i>0) { //first point we keep at zero
					envelope.push([0,0]); //add an empty point to start					
					//store the point and scale it
					var ptNow = 1*multscale*(Number(strArray[i])+DCOffset);
					//use the point to be one part of the envelope, the second part will be
					//a decay of the last value
					if (ptNow>0) {
						if (ptNow -envelope[i-1][0]>maxmove) {
							ptNow = envelope[i-1][0]+maxmove;
						} else if (ptNow-envelope[i-1][0]<-1*maxmove) {
							ptNow = envelope[i-1][0]-maxmove;
						}
						envelope[i][0] = ptNow;
						envelope[i][1] = envelope[i-1][1]/fallaway;
					} else {
						if (ptNow -envelope[i-1][1]>maxmove) {
							ptNow = envelope[i-1][1]+maxmove;
						} else if (ptNow-envelope[i-1][1]<-1*maxmove) {
							ptNow = envelope[i-1][1]-maxmove;
						}
						envelope[i][1] = ptNow;
						envelope[i][0] = envelope[i-1][0]/fallaway;
					}
				}
				numPoints++; //move to next point
			}
			drawSoundWave(circleX, circleY, spr);
		}

		public function drawSoundWave(cx:Number, cy:Number, holdWave:Sprite) {
		
			//draw it
			holdWave.graphics.clear();
			holdWave.graphics.lineStyle(1,lineColor,90);
			holdWave.graphics.beginFill(fillColor);
			holdWave.graphics.moveTo(cx,cy);
			var endpoint = 0;
		
			for (var i=0; i<numPoints; i=i+2) {
				var ypt = envelope[i][0];
				if (ypt>120) {
					ypt=120;
				} else if (ypt<-120) {
					ypt = -120;
				}
				holdWave.graphics.lineTo(cx+i/2,cy+ypt);
				endpoint = i;
			}
			for (i=endpoint; i>=0; i=i-2) {
				ypt = envelope[i][1];
				if (ypt>120) {
					ypt=120;
				} else if (ypt<-120) {
					ypt = -120;
				}
				holdWave.graphics.lineTo(cx+i/2,cy+ypt);
			}
			holdWave.graphics.endFill();
		}
		
		private function doCurl(e:Event):void {
			animCount+=2;
			var cy = circleY-200;
			var cx = circleX-450;
			if (animCount <= 50) {
				curveTail(animCount, watermarkScale, cx,cy);
			}
			else if (animCount <= 100) {
				var moveInc = ((numPoints)/200)*(animCount-49);  //  move the waveform while curling it, to create illusion of spinning
				curveTail(animCount, watermarkScale, cx+moveInc, cy);
			}
		}

							// draw straight waveform with specified percentage of curve at the end
		public function curveTail(percentCurved:Number, div:Number, ccx:Number, ccy:Number) {
			//trace("total data points = "+envelope.length);
			var wd = numPoints/div;
			var curveCount = numPoints*((100-percentCurved)/100);  // point number to begin curve at
			var px:Number;
			var py:Number;
			var p2x:Number;
			var p2y:Number;
			cEnvOut = [];
			cEnvIn = [];
			for (var j=0; j<numPoints; j=j+div) {
				var pt0 = envelope[j][0];
				var pt1 = envelope[j][1];
				if (j>1 && j<numPoints-2) {
					pt0 = (envelope[j-2][0]+envelope[j-1][0]+envelope[j][0]+envelope[j+1][0]+envelope[j+2][0])/5.0;
					pt1 = (envelope[j-2][1]+envelope[j-1][1]+envelope[j][1]+envelope[j+1][1]+envelope[j+2][1])/5.0;
				}
				if (pt0>120) {
					pt0=120;
				} else if (pt0<-120) {
					pt0 = -120;
				}
				if (pt1>120) {
					pt1=120;
				} else if (pt1<-120) {
					pt1 = -120;
				}
				if (j<curveCount) {
					cEnvOut.push([ccx+(j/div),ccy+pt0]);
					cEnvIn.push([ccx+(j/div),ccy+pt1]);
				}
				else {
					var currentAngle:Number = 90+(((j-curveCount)/numPoints)*360);
					var radians = currentAngle * (Math.PI/180);
					px = (pt0-ringsize)*Math.cos(radians);
					py = (pt0-ringsize)*Math.sin(radians);
					p2x = (pt1-ringsize)*Math.cos(radians);
					p2y = (pt1-ringsize)*Math.sin(radians);
					cEnvOut.push([ccx+(curveCount/div)+px,ccy+(ringsize)+py]);
					cEnvIn.push([ccx+(curveCount/div)+p2x,ccy+(ringsize)+p2y]);
				}
			}	
			drawCurve(shpCircle,wd,0);
		}

			// draws shape based on points in array
			// NOTE:  skipping by 2s to reduce the complexity
		private function drawCurve(shp:Shape, len:Number, startNum:Number) {
			shp.graphics.clear();
			shp.graphics.lineStyle(1,lineColor,90);
			shp.graphics.beginFill(fillColor);
			shp.graphics.moveTo(cEnvOut[startNum][0],cEnvOut[startNum][1]);
			for (var j=startNum; j<len; j=j+1) {	// draw the outer outline
				shp.graphics.lineTo(cEnvOut[j][0],cEnvOut[j][1]);
			}
			for (j=len-1; j>=startNum; j=j-1) {		// draw the inner outline
				shp.graphics.lineTo(cEnvIn[j][0],cEnvIn[j][1]);
			}
			shp.graphics.lineTo(cEnvOut[startNum][0],cEnvOut[startNum][1]);
			shp.graphics.endFill();
		}

	}
}